library AssaultmanSMAW initializer init requires LegacySystem

	private function PushUnit_callback takes nothing returns nothing
		local timer t = GetExpiredTimer()
		local unit u = getUnit(t,"u")
		local real angle = getReal(t,"angle")
		local integer steps = getInteger(t,"steps")
		local real stepdist = getReal(t,"stepdist")
		local real x = GetUnitX(u)
		local real y = GetUnitY(u)
		local real x2 = x - stepdist*Cos(angle)
		local real y2 = y - stepdist*Sin(angle)
		local integer end = 0
		if GetWidgetLife(u)>0.405 then
			call PauseUnit(u,true)
			if RectContainsCoords(bj_mapInitialPlayableArea,x2,y2) and GetTerrainCliffLevel(x,y)>=GetTerrainCliffLevel(x2,y2) then
				call SetUnitX(u,x2)
				call SetUnitY(u,y2)
			endif
			call PauseUnit(u,false)
			if GetRandomInt(0,10)==1 then
				if not(IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY)) then
					call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl",x,y))
				else
					call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
				endif
			endif
		else
			set end=1
		endif
		set steps = steps - 1
		call putInteger(t,"steps",steps)
		if steps<=0 or end==1 then
			if not(IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY)) then
				call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl",x,y))
			else
				call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",x,y))
			endif
			call putBoolean(u,"marked_by_explosive",false)
			call FlushHandleLocals(t)
			call ReleaseTimer(t)
		endif
		set u = null
	endfunction

	private  function PushUnit takes unit u, real angle, integer steps, real stepdist, real period returns nothing
		local timer t
		if getBoolean(u,"marked_by_explosive")==true then
			return
		endif
		call putBoolean(u,"marked_by_explosive",true)
		set t = NewTimer()
		call putUnit(t,"u",u)
		call putReal(t,"angle",angle)
		call putInteger(t,"steps",steps)
		call putReal(t,"stepdist",stepdist)
		call TimerStart(t,period,true,function PushUnit_callback)
	endfunction

	private  function ShockwaveSafe takes unit u returns boolean //Shockwave will not affect these units. Must not be netted
		local integer i=GetUnitTypeId(u)
		return i!='e00C' and i!='e00H' and i!='hhou' and i!='hatw' and i!='nten' and i!='n012' and i!='e00J' and i!='o001' and i!='h00K' and i!='h00D' and GetUnitAbilityLevel(u,'Bena')<1 and GetUnitAbilityLevel(u,'Beng')<1 and GetUnitPointValue(u)!=5
	endfunction

	private  function SMAW_Effect takes location target,unit caster, integer id, integer rpg_l, integer rockettype returns nothing
		local real x = GetLocationX(target)
		local real y = GetLocationY(target)
		local real z
		local real x1
		local real y1
		local real theta = 0.0
		local integer n = 8
		local real thetastep = 360.0/n
		local real damage
		local real angle
		local integer A = 1
		local group g
		local rect r = Rect(x-300,y-300,x+300,y+300)
		local unit u = CreateUnit(ConvertedPlayer(id),'e003',x,y,0.0)
		local real blastradius = udg_rpg_radius[rpg_l]
		local real blastdamage = udg_rpg_damage[rpg_l]
		if rockettype==3 then //HEAA
			set blastradius = blastradius*0.5
			set blastdamage = blastdamage*1.25
		endif
		set z = udg_rpg_radius[rpg_l]/2.0
		set g = AMGetUnitsInRange(blastradius, target, null)
		call UnitDamagePoint(caster,0,blastradius,x,y,blastdamage,true,false,udg_SMAWWarhead[id],DAMAGE_TYPE_DEMOLITION,WEAPON_TYPE_WHOKNOWS)
		call ForGroup(g, function killexplosive)
		call DestroyGroup(g)
		set udg_soundpath = "war3mapImported\\Explosion2.mp3"
		call PlaySoundPath.execute()
		set udg_myinteger = rpg_l

		call EnumDestructablesInRect(r,null,function killtree)
		call EnumItemsInRect(r,null,function killitem)

		call RemoveRect(r)
		call KillUnit(u)
		set r = null
		if rockettype==3 then //HEAA
			//call print("frag boom")
			call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl",x,y))
		else
			call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl",x,y))
		endif
		call EarShockArea(x,y,blastradius+150.0)
		set g = AMGetUnitsInRange(blastradius+50,target,null)
		loop
			set u = FirstOfGroup(g)
			exitwhen u==null
			if GetWidgetLife(u)>0.405 and GetUnitAbilityLevel(u,'Avul')<1 and ShockwaveSafe(u) then
				set angle = Atan2(y-GetUnitY(u),x-GetUnitX(u))
				if GetUnitPointValue(u)==50 then
					call PushUnit(u,angle,20,7.5,0.04)
				else
					call PushUnit(u,angle,30,10.0,0.04)
				endif
			endif
			call GroupRemoveUnit(g,u)
		endloop
		call DestroyGroup(g)
		set g = null
		loop
			exitwhen A > n
			set x1 = x+z*Cos(theta)
			set y1 = y+z*Sin(theta)
			if RectContainsCoords(bj_mapInitialPlayableArea,x1,y1) then
			   
				call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl",x1,y1))
			endif
			set theta = theta + thetastep
			set A = A + 1
		endloop
	endfunction

	private  function SMAW_Handler takes unit caster, location spelltarget, integer rpg_l, integer rockettype returns nothing
		local location cast_loc = GetUnitLoc(caster)
		local real d = DistanceBetweenPoints(cast_loc, spelltarget)

		local real x = GetUnitX(caster)
		local real y = GetUnitY(caster)
		local real missilespeed = 2500 //from unit SMAW missile
		local real dx = x - GetLocationX(spelltarget)
		local real dy = y - GetLocationY(spelltarget)
		local real arctime = (d/missilespeed) + 0.2
		local integer id = GetConvertedPlayerId(GetOwningPlayer(caster))
		local unit launcher

		if(arctime<0) then
			set arctime = arctime*-1.00
		endif

		call PolledWait(udg_SMAWLaunch[id])
		if GetWidgetLife(caster)<=0.405 then
			call RemoveLocation(cast_loc)
			set cast_loc = null
		return
		endif
		call UnitAddAbility(caster,'A03F') //Lighting effect
		set launcher = CreateUnitAtLoc(Player(11), 'hctw', cast_loc, 0.0 )
		call UnitApplyTimedLife(launcher, 'Bhwd', 6.0)
		call IssuePointOrderLoc( launcher, "attackground", spelltarget )
		if arctime>1.0 then
			call TriggerSleepAction(1.0)
			call KillUnit(launcher)
			call TriggerSleepAction(arctime - 1.0)
			call SMAW_Effect(spelltarget,caster,id,rpg_l,rockettype)
		else
			call TriggerSleepAction(arctime)
			call SMAW_Effect(spelltarget,caster,id,rpg_l,rockettype)
			call TriggerSleepAction(1.0-arctime)
			call KillUnit(launcher)
		endif
		call RemoveLocation(cast_loc)
		set cast_loc = null
		call UnitRemoveAbility(caster,'A03F')
		if GetWidgetLife(launcher)>0.405 then
			call RemoveUnit(launcher)
		endif
		set launcher = null
	endfunction


	private function SMAWConditions takes nothing returns boolean
		local integer id = GetSpellAbilityId()
		return id=='A01D' or id=='A002' or id=='A036'
	endfunction
	
	private function SMAW takes nothing returns nothing
		local location l
		local unit u
		local integer id = GetSpellAbilityId()
		local integer i = GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))
		if id=='A01D' or id=='A002' or id=='A036' then //Regular,HEDP,HEAA
			set l = GetSpellTargetLoc()
			set u = GetTriggerUnit()
			set udg_SMAWWarhead[i] = ATTACK_TYPE_SIEGE
			if udg_SectorClear==false then
				call FieldChat(u,2.0, udg_Pcolors[i] + GetUnitName(GetTriggerUnit()) + "|r : Fire in the hole!" )
			endif
			if id=='A01D' then
				call SMAW_Handler(u,l,3,1)
			elseif id=='A002' then
				set udg_SMAWWarhead[i] = ATTACK_TYPE_MAGIC
				call SMAW_Handler(u,l,udg_HEDP[i],2)
			else
				call SMAW_Handler(u,l,udg_HEAA[i],3)
			endif
			call PolledWait(5.)
			call RemoveLocation(l)
			set l = null
			set u = null
		endif
	endfunction

	private  function init takes nothing returns nothing
		local trigger t
		set t = CreateTrigger()
		call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT  )
		call TriggerAddCondition(t, Condition(function SMAWConditions))
		call TriggerAddAction(t,function SMAW)
	endfunction

endlibrary